//
//  WebSocketService.swift
//  
//
//  Created by 孙长坦 on 2022/4/18.
//

import Foundation
import UIKit
import Starscream
import Logging

public class WebSocketService: WebSocketDelegate {
    
    public static let shared = WebSocketService()
    
    private var logger = Logger(label: "LibNetwork.WebSocketService")
    
    private let socket: WebSocket?
    
    public var isConnected: Bool = false
    
    private init() {
        guard let appID = Network.shared.appID,
              let webSocketUrl = Network.shared.serviceAddressRepository?.data?.webSocketUrl else {
            socket = nil
            return
        }
        
        guard let url = URL(string: "\(webSocketUrl)/\(appID)") else {
            socket = nil
            return
        }
        
        logger.logLevel = .debug
        
        var request = URLRequest(url: url   )
        request.timeoutInterval = 5
        socket = WebSocket(request: request)
        socket?.delegate = self
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationDidEnterBackground(_:)),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil)
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillEnterForeground(_:)),
            name: UIApplication.willEnterForegroundNotification,
            object: nil)
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillTerminate(_:)),
            name: UIApplication.willTerminateNotification,
            object: nil)
    }
    
    
    @objc func applicationDidEnterBackground(_ notification: NSNotification) {
        socket?.disconnect()
    }
    
    @objc func applicationWillEnterForeground(_ notification: NSNotification) {
        socket?.connect()
    }
    
    @objc func applicationWillTerminate(_ notification: NSNotification) {
        socket?.disconnect()
    }
    
    func initWebSocket() {
        
    }
    
    func connect() {
        socket?.connect()
    }
    
    func disconnect() {
        socket?.disconnect()
    }
    
    public func didReceive(event: WebSocketEvent, client: WebSocket) {
        switch event {
        case .connected(let headers):
            isConnected = true
            logger.info("webSocket is connected: \(headers)")
            
        case .disconnected(let reason, let code):
            isConnected = false
            logger.info("webSocket is disconnected: \(reason) with code: \(code)")
            
        case .text(let string):
            logger.info("Received text: \(string)")
            
        case .binary(let data):
            logger.info("Received data: \(data.count)")
            
        case .ping(_):
            logger.info("webSocket ping")
            
        case .pong(_):
            logger.info("webSocket pong")
            
        case .viabilityChanged(let value):
            logger.info("webSocket viabilityChanged = \(value)")
            
        case .reconnectSuggested(let value):
            logger.info("webSocket reconnectSuggested = \(value)")
            
        case .cancelled:
            isConnected = false
            logger.info("webSocket cancelled")
            
        case .error(let error):
            isConnected = false
            logger.info(Logger.Message(stringLiteral: error?.localizedDescription ?? "webSocket error"))
        }
    }
}
